开源 Agents - Open Manus 源码解读
ReAct
核心理念是 ReAct : "思考-行动"循环
框架思路参考: www.promptingguide.ai
ReAct 和 COT 的区别
COT 举例: 问题: 如果一个房间有 3 张桌子,每张桌子上有 4 把椅子,总共有多少把椅子? 推理: 每张桌子有 4 把椅子,一共有 3 张桌子,所以总数是 3 × 4 = 12。 答案: 12 把椅子。
ReAct 举例: 问题: 北京的天气如何? 推理: 我需要查询北京的实时天气信息。 行动: 查询天气 API。 结果: 北京当前温度为 20°C,晴天。 答案: 北京当前温度为 20°C,晴天。
Open Manus 主要架构图:

规划 Planning : 任务分解、子任务生成及自我反思
- Reason + Act(ReAct)推理-行动-反馈
- Plan-and-Solve(PS) 显式分解任务为子目标并分步执行,提升复杂任务的推理能力
记忆 Memory : 长期记忆存储与上下文管理,用于处理复杂任务
工具使用 Tool Usage : 通过API或外部工具增强Agent的能力(如搜索、文件操作,代码执行等) Open Manus 内所有的都是 Agent, 通过 Agent 之间的相互调用完成任务
Reason + Act(ReAct)
主要步骤
- 初始化:创建Manus实例,加载系统提示词和可用工具。
- 用户输入:接收用户的自然语言指令。
- 思考阶段:调用LLM分析当前状态,决定下一步行动。
- 行动阶段:执行选定的工具,获取结果。
- 循环迭代:将结果反馈给LLM,继续思考和行动,直到任务完成
核心方法
- Think - 代理会根据当前状态进行推理,决定下一步的动作
- Act - 代理会执行决定的动作,并返回结果 - Observation
- Step - 记录步骤,驱动代理执行思考和行动-循环迭代
如下手画代码流程


详细框架流程图

源码:BaseAgent 核心属性
- 基本信息:
name:代理的唯一名称,必须提供description:可选的代理描述
- 提示系统:
system_prompt:系统级指令提示,用于初始化代理next_step_prompt:决定下一步行动的提示
- 依赖组件:
llm:语言模型实例,默认创建一个新的 LLM 实例memory:代理的内存存储,用于保存消息历史state:当前代理状态,默认为 IDLE
- 执行控制:
max_steps:终止前的最大步骤数,默认为 10current_step:当前执行步骤,默认为 0duplicate_threshold:检测重复响应的阈值,默认为 2
案例: 生成一篇关于熬夜对健康的影响的调研报告
以下流程展示了 Open Manus 基于 ReAct 模式,从接收用户任务到输出完整调研报告的完整执行过程。每一步都遵循「思考 → 行动 → 观察」的循环。
① 用户输入与任务解析:用户提交自然语言指令「生成一篇关于熬夜对健康的影响的调研报告」,Agent 接收并解析任务意图。

② 思考阶段(Think):LLM 分析当前状态,将复杂任务拆解为可执行的子目标,并决定首先需要检索相关文献或资料。

③ 行动阶段(Act):Agent 选择并调用合适的工具(如搜索 API),执行信息检索动作。

④ 观察结果(Observation):工具返回检索到的资料,Agent 将结果作为上下文反馈给 LLM。

⑤ 迭代推理:根据已有信息,LLM 判断是否需要继续搜索、补充数据,或进入报告撰写阶段。

⑥ 内容生成:在信息充足后,Agent 开始整合资料,按调研报告结构生成正文内容。

⑦ 输出完成:完成报告撰写,返回最终成果给用户,结束 ReAct 循环。

Planning
class PlanningFlow(BaseFlow):
"""A flow that manages planning and execution of tasks using agents."""
llm: LLM =Field(default_factory=lambda: LLM())
planning_tool:PlanningTool=Field(default_factory=PlanningTool)
executor_keys:List[str]=Field(default_factory=list)
active_plan_id:str=Field(default_factory=lambda:f"plan_{int(time.time())}")
current_step_index:Optional[int]= None- 依赖组件:
llm:语言模型实例,用于与 LLM 交互planning_tool:规划工具实例,用于创建和管理执行计划
- 执行控制:
executor_keys:执行代理的键列表,默认为空列表active_plan_id:当前活动计划的 ID,默认使用时间戳生成current_step_index:当前步骤索引,默认为 None
执行流程:
- 验证主代理是否可用
- 如果提供了输入文本,创建初始计划
- 验证计划是否创建成功
- 进入执行循环:
- 获取当前要执行的步骤
- 如果没有更多步骤或计划已完成,调用 _finalize_plan并结束循环
- 根据步骤类型选择合适的执行代理
- 执行当前步骤并收集结果
- 检查代理是否想要终止执行
- 返回执行结果
- 捕获并处理异常
Open Manus message
Open Manus 的对话与执行状态通过 Memory 中的 messages 列表维护。每条消息都有明确的 role 和 content,共同构成 Agent 的上下文与执行轨迹。
消息角色(role):
- user:用户指令、系统引导提示(如「根据用户需求主动选择工具」)、浏览器截图等上下文
- assistant:LLM 的推理、规划与回复,以及通过
tool_calls触发的工具调用 - tool:工具执行后的观测结果(如
browser_use的搜索/提取结果、str_replace_editor的文件创建结果等)
执行流程在 messages 中的体现:用户发起请求后,Agent 先规划步骤并回复,再发起工具调用;工具返回的 Observed output 作为新消息追加;系统会插入「下一步该做什么」等引导,驱动下一轮 Think-Act 循环,直到调用 terminate 结束任务。

Suna
类似 open manus (不过源码完整体不够,改了好多地方才跑起来) Suna 的 Agent 核心是整个系统最核心的部分,基于ReAct(Reasoning + Action)模式运作。
技术路线:

async def run_agent(thread_id, sandbox, stop_event, add_message):
"""Agent核心执行循环"""
iteration = 0
max_iterations = 10
# 发送开始状态
add_message(status_message("thread_run_start"))
while iteration < max_iterations:
# 1. 检查停止信号
if stop_event.is_set():
add_message(status_message("finish", reason="stopped"))
break
# 2. 获取视觉状态(如浏览器截图和DOM)
browser_state = get_latest_browser_state(thread_id)
temp_messages = []
if browser_state:
# 把浏览器状态转为临时消息(LLM能"看见"当前页面)
temp_messages.append(format_browser_state_message(browser_state))
# 3. 获取处理后的对话历史(可能已包含摘要)
history = get_formatted_messages(thread_id)
# 4. 准备完整上下文并调用LLM
add_message(status_message("thinking"))
response_processor = ResponseProcessor(
sandbox=sandbox,
tool_registry=tool_registry,
add_message_callback=add_message
)
# 5. 流式处理LLM响应(实时解析XML并执行工具)
finish_reason = await response_processor.process_streaming_response(
call_llm(history + temp_messages)
)
# 6. 检查是否需要结束循环
if finish_reason in ["ask", "complete"]:
add_message(status_message("finish", reason=finish_reason))
break
iteration += 1
# 如果达到最大迭代次数
if iteration >= max_iterations:
add_message(status_message("finish", reason="max_iterations"))
# 发送结束状态
add_message(status_message("thread_run_end"))
但在工程化上做的更好。 在内存、数据库、沙盒等方面有一定的参考价值
且每个工具使用@xml_schema装饰器定义其XML接口
思考
无论是哪一种 Agent 的路线,最感觉最关键的部分是 prompt 的设计,一好的 prompt 驱动整个流程。